home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / PCI Driver Development Kit / • Samples / Driver Samples / Video samples / GDX 950717 / GDX / GraphicsOSS.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-20  |  46.1 KB  |  1,374 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        GraphicsOSS.c
  3.  
  4.     Contains:    This file implements the (weak) abstraction layer for Operating Systems Services (OSS)
  5.  
  6.     Written by:    Sean Williams, Kevin Williams
  7.  
  8.     Copyright:    © 1994-1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>     7/17/95    SW        Added GraphicsOSS DoVSLInterruptService() for hardware which 
  13.                                      doesn't implement true hardware VBL interrupts.
  14.          <1>     4/15/95    SW        First Checked In
  15.  
  16. */
  17.  
  18. #include "GraphicsPriv.h"
  19. #include "GraphicsOSS.h"
  20. #include "GraphicsCore.h"
  21. #include "GraphicsHAL.h"
  22. #include "GraphicsCoreStatus.h"
  23.  
  24. #include <Devices.h>                // IOCommandID, etc
  25. #include <DriverServices.h>            // for string functions
  26. #include <Errors.h>
  27. #include <Interrupts.h>                // handler stuff
  28. #include <Files.h>                    // CntrlParam
  29. #include <Kernel.h>                    // AddressSpace
  30. #include <NameRegistry.h>            // IOCommandContents.initialinfo has RegEntryID
  31. #include <Types.h>
  32. #include <VideoServices.h>
  33.  
  34.  
  35.  
  36. //
  37. // GraphicsNonVolatile
  38. //    This structure describes the PropertyValue that is needed for the
  39. //    GetPreferredConfiguration and SetPreferredConfiguration calls.  The DisplayCode is saved in
  40. //    addition to the DisplayModeID and the DepthMode since the core looks at the displayCode from the
  41. //    previous boot.  Since a device is limited to 8 bytes of NVRAM information, the GraphicsNonVolatile
  42. //    stucture holds the compressed information that the GraphicsPreferredStructure expects.
  43. //    4 bytes are reserved for the "Core", 4 bytes are reserved for the HAL
  44. //
  45. typedef struct GraphicsNonVolatile GraphicsNonVolatile;
  46. struct GraphicsNonVolatile 
  47. {
  48.     UInt8 reserved;                    // Reserved for future use by the core
  49.     UInt8 mappedDisplayModeID;
  50.     UInt8 mappedDepthMode;
  51.     UInt8 mappedDisplayCode;        // Save the DisplayCode in case the user switches monitors
  52.     UInt32 halData;                    // The HAL gets 4 bytes of the NVRAM data
  53. };
  54.  
  55.  
  56. typedef UInt32 OSSMapDirection;
  57. enum
  58. {
  59.     kOSSMapExpand = 0,
  60.     kOSSMapCompress
  61. };
  62.  
  63.  
  64.  
  65. //
  66. // OSSData (IPI)
  67. //    This structure contains the 'globals' needed to maintain the necessary state
  68. //    information regarding the graphics core.
  69. //
  70. typedef struct OSSData OSSData;
  71. struct OSSData
  72. {
  73.     RegEntryID regEntryID;                        // RegEntryID describing Graphics HW
  74.     InterruptSetMember interruptSetMember;        // The 'driver-ist'
  75.     InterruptServiceIDType vslServiceID;        // VSL service ID...run task for this id
  76.     void *vblRefCon;                            // Address of HAL's refCon for interrupt functions
  77.     VBLHandler *halVBLHandler;                    // Address of HAL's vbl handler
  78.     VBLEnabler *halVBLEnabler;                    // Address of HAL's vbl enabler
  79.     VBLDisabler *halVBLDisabler;                // Address of HAL's vbl disabler
  80.     void *defaultRefCon;                        // Default refCon
  81.     InterruptHandler defaultVBLHandler;            // Default vbl handler
  82.     InterruptEnabler defaultVBLEnabler;            // Default vbl enabler
  83.     InterruptDisabler defaultVBLDisabler;        // Default vbl disabler
  84.     Boolean hasInterruptSetMember;                // Found kISTPropertyName
  85.     Boolean chainDefault;                        // 'true' if HAL wants default enabler/disabler vbl 
  86.                                                 // routines to be called after HAL routines
  87.     Boolean installedHALVBLRoutines;            // 'true' if successfully installed HAL VBL routines
  88.     Boolean vslServiceIDValid;                    // 'true' when OSS has a valid VSLServiceID
  89. };
  90.  
  91.  
  92.  
  93. // OSS internal prototypes
  94.  
  95. static GDXErr GraphicsOSSInitialize(const RegEntryID *regEntryID);
  96. static OSSData *GraphicsOSSGetOSSData(void);
  97. static GDXErr OSSMapPreference(OSSMapDirection mapDirection, GraphicsNonVolatile *graphicsNonVolatile,
  98.         GraphicsPreferred *graphicsPreferred);
  99. static InterruptMemberNumber GraphicsOSSVBLInterruptHandler(InterruptSetMember interruptSetMember,
  100.         void *vblRefCon, UInt32 theIntCount);
  101. static void GraphicsOSSVBLInterruptEnabler(InterruptSetMember interruptSetMember, void *vblRefCon);
  102. static Boolean GraphicsOSSVBLInterruptDisabler(InterruptSetMember interruptSetMember, 
  103.             void *vblRefCon);
  104.  
  105. OSSData gOSSData;
  106.  
  107.  
  108.  
  109. //=====================================================================================================
  110. //
  111. // DoDriverIO()
  112. //    This is the entry point for the native Graphics Driver.
  113. //
  114. //=====================================================================================================
  115. OSErr DoDriverIO (AddressSpaceID spaceID, IOCommandID ioCommandID, IOCommandContents ioCommandContents, IOCommandCode ioCommandCode,
  116.         IOCommandKind ioCommandKind)
  117.  
  118. {
  119.     OSErr err = noErr;                // Assume success.  If we get an ioCommandCode that is not
  120.                                     // supported just return noErr.
  121.                                     
  122.  
  123.     switch (ioCommandCode)
  124.     {
  125.     case kInitializeCommand:
  126.         err = GraphicsOSSInitialize(&ioCommandContents.initialInfo->deviceEntry);
  127.         err = GraphicsInitialize(ioCommandContents.initialInfo->refNum, &ioCommandContents.initialInfo->deviceEntry, spaceID);
  128.         break;
  129.  
  130.     case kReplaceCommand:
  131.         err = GraphicsOSSInitialize(&ioCommandContents.initialInfo->deviceEntry);
  132.         err = GraphicsReplace(ioCommandContents.initialInfo->refNum, &ioCommandContents.initialInfo->deviceEntry, spaceID);
  133.         break;
  134.  
  135.     case kOpenCommand:
  136.         err = GraphicsOpen();
  137.         break;
  138.         
  139.     case kCloseCommand:
  140.         err = GraphicsClose();
  141.         break;
  142.         
  143.     case kControlCommand:
  144.         err = GraphicsControl((CntrlParam *) ioCommandContents.pb);
  145.         break;
  146.         
  147.     case kStatusCommand:
  148.         err = GraphicsStatus((CntrlParam *) ioCommandContents.pb);
  149.         break;
  150.     
  151.     case kFinalizeCommand:
  152.         GraphicsOSSKillPrivateData();
  153.         err = GraphicsFinalize(ioCommandContents.finalInfo->refNum, &ioCommandContents.finalInfo->deviceEntry);
  154.         break;
  155.  
  156.     case kSupersededCommand:
  157.         GraphicsOSSKillPrivateData();
  158.         err = GraphicsSupersede(ioCommandContents.finalInfo->refNum, &ioCommandContents.finalInfo->deviceEntry);
  159.         break;
  160.  
  161.     case kReadCommand:                // We do not support 'Read' or 'Write' commands
  162.     case kWriteCommand:                
  163.         err = noErr;
  164.         break;        
  165.  
  166.     default:                        // an error
  167.         err = controlErr;
  168.     }
  169.     
  170.     // If an immediate command, return error result right now, otherwise let everything be processed
  171.     // by IOCommandIsComplete()  (Initialize, Finalize... are immediate)
  172.     
  173.     if (kImmediateIOCommandKind == ioCommandKind)
  174.         return err;
  175.     else
  176.         return IOCommandIsComplete( ioCommandID, err );
  177.  
  178. }
  179.  
  180.  
  181.  
  182. //=====================================================================================================
  183. //
  184. // GraphicsOSSInitialize()
  185. //
  186. //    The OSS saves the 'regEntryID'.  More importantly, the OSS looks for the kISTPropertyName property
  187. //    and saves the the 'InterruptSetMember' pertaining to the 'kISTChipInterruptSource'
  188. //
  189. //    Note: OSS assumes that a driver's "driver-ist" only pertains to VBL's
  190. //
  191. //=====================================================================================================
  192. static GDXErr GraphicsOSSInitialize(const RegEntryID *regEntryID)
  193. {
  194.     ISTProperty istProperty;
  195.     OSSData *ossData = GraphicsOSSGetOSSData();
  196.  
  197.     GDXErr err = kGDXErrUnknownError;                            // Assume failure
  198.     
  199.     ossData->hasInterruptSetMember = false;                        // Don't yet have interrtuptSetMember
  200.     ossData->vslServiceIDValid = false;                            // No VSLServiceID yet
  201.  
  202.     RegistryEntryIDCopy(regEntryID, &ossData->regEntryID);        // Save the regEntryID,
  203.  
  204.     // Retrieve the ISTProperty.
  205.     // The ISTProperty is an array consisting of several InterruptSetMembers.
  206.     // The only InterruptSetMember of interest is the 'kISTChipInterruptSource', since
  207.     // the others relate to DMA, which is not applicable here.
  208.  
  209.     err = GraphicsOSSGetProperty(regEntryID, kISTPropertyName, istProperty, sizeof(ISTProperty));
  210.     
  211.     if (err)
  212.         goto ErrorExit;
  213.         
  214.     ossData->interruptSetMember = istProperty[kISTChipInterruptSource];
  215.     ossData->hasInterruptSetMember = true;                        // Have valid interrtuptSetMember
  216.  
  217. ErrorExit:
  218.  
  219.     return err;
  220. }    
  221.  
  222.  
  223.  
  224. //=====================================================================================================
  225. //
  226. // GraphicsOSSKillPrivateData()
  227. //
  228. //    Dispose of the OSS's private data, remove interrupt handlers, and remove driver from VSL queue
  229. //
  230. //=====================================================================================================
  231. void GraphicsOSSKillPrivateData()
  232. {
  233.     OSSData *ossData = GraphicsOSSGetOSSData();
  234.  
  235.     RegistryEntryIDDispose(&ossData->regEntryID);
  236.     // Disable the external interrupts before removing the interrupt functions
  237.     
  238.     if (ossData->installedHALVBLRoutines)
  239.     {
  240.         // If the HAL installed a disabler function call it.  Otherwise call the default enabler
  241.         if (NULL != ossData->halVBLDisabler)
  242.             (void) GraphicsOSSVBLInterruptDisabler(ossData->interruptSetMember, ossData->vblRefCon);
  243.         else
  244.             (void) GraphicsOSSVBLDefaultDisabler();
  245.         
  246.         // Interrupts are disabled, so reinstall the default enablers
  247.         (void) InstallInterruptFunctions(ossData->interruptSetMember.setID, 
  248.                 ossData->interruptSetMember.member, ossData->defaultRefCon, 
  249.                 ossData->defaultVBLHandler, ossData->defaultVBLEnabler, ossData->defaultVBLDisabler);
  250.     }
  251.     
  252.     if (ossData->vslServiceIDValid)
  253.     {
  254.         (void) VSLDisposeInterruptService(ossData->vslServiceID);
  255.         ossData->vslServiceIDValid = false;
  256.     }
  257.     
  258. }
  259.  
  260.  
  261.  
  262. //=====================================================================================================
  263. //
  264. // GraphicsOSSGetOSSData()
  265. //
  266. //    Return the pointer to the global OSS data.
  267. //    (Yes...you guessed it...it just returns the address of the global.  However, use your
  268. //    access functions in the event the way-coolness of CFM is ever lost.  You have been warned.)
  269. //
  270. //=====================================================================================================
  271. static OSSData *GraphicsOSSGetOSSData(void)
  272. {
  273.     return (&gOSSData);
  274. }
  275.  
  276.  
  277.  
  278. //=====================================================================================================
  279. //
  280. // GraphicsOSSSaveProperty()
  281. //    The OSS calls the Name Registry to save information.  The OSS doesn't care about the content.
  282. //
  283. //            ->    regEntryID            Name Registry RegEntryID that should have the propertyName
  284. //            ->    propertyName        c string property name
  285. //            ->    propertyValue        void * to buffer containing the data
  286. //            ->    propertySize        size of the data
  287. //            ->    ossPropertyStorage    GDX internal flags that describe how the property should get saved
  288. //                    kOSSPropertyAvailableAtBoot, available at boot (saved across boots)
  289. //                    kOSSPropertyAvailableAtDisk, available once disk is around (saved across boots)
  290. //                    kOSSPropertyVolatile, property not saved across boots
  291. //
  292. //=====================================================================================================
  293. GDXErr GraphicsOSSSaveProperty(const RegEntryID *regEntryID, const char *propertyName,
  294.         const void *propertyValue, ByteCount propertySize, OSSPropertyStorage ossPropertyStorage)
  295. {
  296.  
  297.     RegPropertyModifiers modifiers;            // Set modifers based on ossPropertyStorage
  298.                                             
  299.     RegPropertyValueSize valueSize;            
  300.     OSErr nameRegistryErr;                    // In the event of NameRegistry errors
  301.     UInt32 propertyNameLength;                // Make sure proprtyName is not too long
  302.     
  303.     RegModifiers savedToNVRAMAndDiskMask = (kRegPropertyValueIsSavedToNVRAM | 
  304.                                             kRegPropertyValueIsSavedToDisk);    
  305.  
  306.     GDXErr err = kGDXErrUnknownError;                                // Assume failure
  307.     
  308.  
  309.     // Is the 'kRegMaximumPropertyNameLength < propertyName length'?
  310.     propertyNameLength = CStrLen(propertyName);
  311.     if (kRegMaximumPropertyNameLength < propertyNameLength)
  312.     {
  313.         err = kGDXErrOSSPropertyNameLengthTooLong;
  314.         goto ErrorExit;
  315.     }
  316.     
  317.     // Is the OSSPropertyStorage valid?
  318.     if (     (kOSSPropertyAvailableAtBoot != ossPropertyStorage) &&
  319.             (kOSSPropertyAvailableAtDisk != ossPropertyStorage) &&
  320.             (kOSSPropertyVolatile != ossPropertyStorage) )
  321.     {
  322.         err = kGDXErrOSSPropertyStorageInvalid;
  323.         goto ErrorExit;
  324.     }
  325.             
  326.     // Try to get the size of the propertyName to make sure that it exists
  327.     nameRegistryErr = RegistryPropertyGetSize(regEntryID, propertyName, &valueSize);
  328.     if (nameRegistryErr)
  329.     {
  330.         // Create the property since it didn't exist
  331.         nameRegistryErr = RegistryPropertyCreate(regEntryID, propertyName, propertyValue, propertySize);
  332.         
  333.         if (nameRegistryErr)
  334.         {
  335.             err = kGDXErrOSSUnableToCreateProperty;
  336.             goto ErrorExit;    
  337.         }
  338.         
  339.     }
  340.     else
  341.     {        
  342.         // Property already exists so just set the property to the new value
  343.         nameRegistryErr = RegistryPropertySet(regEntryID, propertyName, propertyValue, propertySize);
  344.     
  345.         if (nameRegistryErr)
  346.         {
  347.             err = kGDXErrOSSUnableToSetPropertyValue;
  348.             goto ErrorExit;
  349.         }
  350.     }
  351.     
  352.     // The property exists and has been set to the correct value.  Get  the modifiers so the can
  353.     // be altered appropriately.
  354.     
  355.     nameRegistryErr = RegistryPropertyGetMod(regEntryID, propertyName, &modifiers);
  356.  
  357.     if (nameRegistryErr)
  358.     {
  359.         err = kGDXErrOSSUnableToSavePropertyStorage;
  360.         goto ErrorExit;
  361.     }
  362.     
  363.     // Clear the bits corresponding to where to store property, in case they had a different
  364.     // previous value.
  365.     
  366.     modifiers &= ~savedToNVRAMAndDiskMask;
  367.     
  368.     if (kOSSPropertyAvailableAtBoot == ossPropertyStorage)
  369.         modifiers |= kRegPropertyValueIsSavedToNVRAM;                // Property saved to NVRAM
  370.     else if (kOSSPropertyAvailableAtDisk == ossPropertyStorage)
  371.         modifiers |=  kRegPropertyValueIsSavedToDisk;                // Property saved to disk
  372.  
  373.     nameRegistryErr = RegistryPropertySetMod(regEntryID, propertyName, modifiers);
  374.  
  375.     if (nameRegistryErr)
  376.     {
  377.         err = kGDXErrOSSUnableToSavePropertyStorage;
  378.         goto ErrorExit;
  379.     }
  380.  
  381.     err = kGDXErrNoError;
  382.     
  383. ErrorExit:
  384.  
  385.     return err;
  386.  
  387. }
  388.  
  389.  
  390.  
  391. //=====================================================================================================
  392. //
  393. // GraphicsOSSGetProperty()
  394. //    The OSS calls the Name Registry to get information.  The OSS doesn't care about the content.
  395. //    If the property doesn't exist...so it goes, that's an error
  396. //
  397. //            ->    regEntryID            Name Registry RegEntryID that should have the propertyName
  398. //            ->    propertyName        c string property name
  399. //            ->    propertyValue        void* to buffer to hold the data
  400. //            ->    propertySize        expected size of the data
  401. //
  402. //=====================================================================================================
  403. GDXErr GraphicsOSSGetProperty(const RegEntryID *regEntryID, const char *propertyName,
  404.         void *propertyValue, ByteCount propertySize)
  405. {
  406.  
  407.     RegPropertyValueSize valueSize;                            // Actual value size of propertyName
  408.     OSErr nameRegistryErr;                                    // In the event of NameRegistry errors
  409.     
  410.     GDXErr err = kGDXErrUnknownError;                        // Assume failure
  411.     
  412.     // Does the PropertyName exist? Is the storage provided by the caller big enough to hold data?
  413.     nameRegistryErr = RegistryPropertyGetSize(regEntryID, propertyName, &valueSize);
  414.     if (nameRegistryErr)
  415.     {
  416.         err = kGDXErrOSSNoProperyNameAndValue;
  417.         goto ErrorExit;
  418.     }
  419.  
  420.     if (valueSize > propertySize)
  421.     {
  422.         err = kGDXErrOSSPropertySizeExceedsBuffer;
  423.         goto ErrorExit;
  424.     }
  425.  
  426.     // The propertyValue exists and can be held in the buffer 'propertyValue'
  427.     nameRegistryErr = RegistryPropertyGet(regEntryID, propertyName, propertyValue, &valueSize);
  428.     if (nameRegistryErr)
  429.     {
  430.         err = kGDXErrOSSUnableToGetPropertyValue;
  431.         goto ErrorExit;
  432.     }
  433.  
  434.     if (valueSize != propertySize)
  435.     {
  436.         err = kGDXErrOSSUnexpectedPropertySize;
  437.         goto ErrorExit;
  438.     }
  439.  
  440.     err = kGDXErrNoError;
  441.     
  442. ErrorExit:
  443.  
  444.     return err;
  445.  
  446. }
  447.  
  448.  
  449.  
  450. //=====================================================================================================
  451. //
  452. // GraphicsOSSDeleteProperty()
  453. //    The OSS calls the System Registry to delete Properties.  It doesn't care what property
  454. //    
  455. //
  456. //            ->    regEntryID        the System Registry RegEntryID that should have the propertyName
  457. //                    sure, the OSS should already have this and the Core and HAL shouldn't need to know 
  458. //                    about the existance of a RegEntryID but since the OSS has no other data...
  459. //                    let it slide.
  460. //                                
  461. //            ->    propertyName        c string property name
  462. //
  463. //=====================================================================================================
  464. GDXErr GraphicsOSSDeleteProperty(const RegEntryID *regEntryID, const char *propertyName)
  465. {
  466.  
  467.     RegPropertyValueSize valueSize;        // actual value size of propertyName
  468.     OSErr nameRegistryErr;                // record System Registry Errors
  469.     
  470.     GDXErr err = kGDXErrUnknownError;                                // Assume failure
  471.     
  472.     nameRegistryErr = RegistryPropertyDelete(regEntryID, propertyName);
  473.     if (nameRegistryErr)
  474.     {
  475.         err = kGDXErrOSSNoProperyNameAndValue;
  476.         goto ErrorExit;
  477.     }
  478.  
  479.  
  480.     err = kGDXErrNoError;
  481.     
  482. ErrorExit:
  483.  
  484.     return err;
  485.  
  486. }
  487.  
  488.  
  489.  
  490. //=====================================================================================================
  491. //
  492. // GraphicsOSSSetCorePref()
  493. //    The OSS calls the System Registry to get information.  The "Core" preferences are saved in the
  494. //    first 4 bytes of the "gprf" nvram property.  The data is saved in a compressed format.  Hence the
  495. //    OSS will translate the grpf data into the GraphicsPreferred data that the core expects.  The
  496. //    4 bytes reserved for the HAL's is ignored.
  497. //    
  498. //
  499. //            ->    regEntryID            the System Registry RegEntryID that should have the propertyName
  500. //            ->    graphicsPreferred    buffer to hold the GraphicsPreferred data
  501. //                                
  502. //    For this routine, the relevant fields of the 'GraphicsPreferred' structure are as follows:
  503. //
  504. //          ->  displayModeID    should be the current displayModeID and will be used on next boot
  505. //          ->  depthMode        should be the current depthMode and will be used on the next boot
  506. //          ->    displayCode        the type of display attached.  If the display changes between boots
  507. //                                the displayModeID and the depthMode will be ignored.
  508. //
  509. //=====================================================================================================
  510. GDXErr GraphicsOSSSetCorePref(const RegEntryID *regEntryID, GraphicsPreferred *graphicsPreferred)
  511. {
  512.  
  513.     RegPropertyModifiers modifiers;            // set modifers based on ossPropertyStorage
  514.     RegModifiers savedToNVRAMAndDiskMask =  (kRegPropertyValueIsSavedToNVRAM |
  515.                                             kRegPropertyValueIsSavedToDisk);
  516.                                             
  517.     RegPropertyValueSize valueSize;        // actual value size of kPreferredConfigurationName property
  518.     RegPropertyValueSize expectedValueSize = sizeof(GraphicsNonVolatile);
  519.     GraphicsNonVolatile graphicsNonVolatile;        // actual data stored in nvram
  520.     OSErr nameRegistryErr;                // record System Registry Errors
  521.     
  522.     GDXErr err = kGDXErrUnknownError;                                // Assume failure
  523.  
  524.     err = OSSMapPreference(kOSSMapCompress, &graphicsNonVolatile, graphicsPreferred);
  525.     if (err)
  526.         goto ErrorExit;
  527.         
  528.     // Does the propertyName exists and is the storage provided by the caller big enough to hold data
  529.     nameRegistryErr = RegistryPropertyGetSize(regEntryID, kPreferredConfigurationName, &valueSize);
  530.     if (nameRegistryErr)
  531.     {
  532.     
  533.         // Create the property since it didn't exist
  534.         graphicsNonVolatile.reserved = 0;
  535.         graphicsNonVolatile.halData = 0;
  536.  
  537.         nameRegistryErr = RegistryPropertyCreate(regEntryID,kPreferredConfigurationName, 
  538.             &graphicsNonVolatile,sizeof(GraphicsNonVolatile));
  539.  
  540.         if (nameRegistryErr)
  541.         {
  542.             err = kGDXErrOSSUnableToCreateProperty;
  543.             goto ErrorExit;    
  544.         }
  545.         // The property exists and has been set to the correct value.  Now set the modifiers
  546.         nameRegistryErr = RegistryPropertyGetMod(regEntryID, kPreferredConfigurationName, &modifiers);
  547.     
  548.         if (nameRegistryErr)
  549.         {
  550.             err = kGDXErrOSSUnableToSavePropertyStorage;
  551.             goto ErrorExit;
  552.         }
  553.         
  554.         modifiers &= ~savedToNVRAMAndDiskMask;                    // Be paranoid and clear these bits
  555.         modifiers |= kRegPropertyValueIsSavedToNVRAM;            // Set them to store in NVRAM
  556.     
  557.         nameRegistryErr = RegistryPropertySetMod(regEntryID, kPreferredConfigurationName, modifiers);
  558.     
  559.         if (nameRegistryErr)
  560.         {
  561.             err = kGDXErrOSSUnableToSavePropertyStorage;
  562.             goto ErrorExit;
  563.         }
  564.  
  565.  
  566.     }
  567.     else
  568.     {
  569.         // Property already exists so just set the property to the new value
  570.         if (valueSize > expectedValueSize)
  571.         {
  572.             // Hmmmm...for some reason, the valueSize is bigger than expected.  Rather than returning
  573.             // an error, kill  the old property and create a new property of the correct size
  574.             
  575.             graphicsNonVolatile.mappedDisplayModeID = 0;
  576.             graphicsNonVolatile.mappedDepthMode = 0;
  577.             graphicsNonVolatile.mappedDisplayCode = 0;
  578.             graphicsNonVolatile.reserved = 0;
  579.             graphicsNonVolatile.halData = 0;
  580.             
  581.             nameRegistryErr = RegistryPropertySet(regEntryID, kPreferredConfigurationName, 
  582.                 &graphicsNonVolatile,sizeof(GraphicsNonVolatile));
  583.         
  584.             if (nameRegistryErr)
  585.             {
  586.                 err = kGDXErrOSSUnableToSetPropertyValue;
  587.                 goto ErrorExit;
  588.             }
  589.             
  590.         // Continue on like nothing happend
  591.         
  592.         }
  593.     
  594.         // The propertyValue exists and can be held in the buffer 'graphicsNonVolatile'
  595.  
  596.         nameRegistryErr = RegistryPropertyGet(regEntryID, kPreferredConfigurationName,
  597.                 &graphicsNonVolatile, &valueSize);
  598.     
  599.         if (nameRegistryErr)
  600.         {
  601.             err = kGDXErrOSSUnableToGetPropertyValue;
  602.             goto ErrorExit;
  603.         }
  604.         
  605.         if (valueSize != expectedValueSize)
  606.         {
  607.             err = kGDXErrOSSUnexpectedPropertySize;
  608.             goto ErrorExit;
  609.         }
  610.     
  611.         // The 'kPreferredConfigurationName' property was found.  Translate the GraphicsPreferred 
  612.         // data into the compressed format
  613.         
  614.         err = OSSMapPreference(kOSSMapCompress, &graphicsNonVolatile, graphicsPreferred);
  615.         if (err)
  616.             goto ErrorExit;
  617.             
  618.         nameRegistryErr = RegistryPropertySet(regEntryID, kPreferredConfigurationName, 
  619.                 &graphicsNonVolatile,sizeof(GraphicsNonVolatile));
  620.  
  621.         if (nameRegistryErr)
  622.         {
  623.             err = kGDXErrOSSUnableToSetPropertyValue;
  624.             goto ErrorExit;
  625.         }
  626.     }
  627.  
  628.     err = kGDXErrNoError;
  629.     
  630. ErrorExit:
  631.  
  632.     return err;
  633.  
  634. }
  635.  
  636.  
  637.  
  638. //=====================================================================================================
  639. //
  640. // GraphicsOSSGetCorePref()
  641. //    The OSS calls the Name Registry to get information.  The "Core" preferences are saved in the
  642. //    first 4 bytes of the 'gprf' NVRAM property.  The data is saved in a compressed format.  Hence the
  643. //    OSS will translate the 'grpf' data into the GraphicsPreferred data that the core expects.  The
  644. //    4 bytes reserved for the HAL's is ignored.
  645. //    
  646. //
  647. //            ->    regEntryID            Name Registry RegEntryID that should have the propertyName
  648. //            <-    graphicsPreferred    buffer to hold the GraphicsPreferred data
  649. //                                
  650. //    For this routine, the relevant fields of the 'GraphicsPreferred' structure are as follows:
  651. //
  652. //          <-  displayModeID    should be the current displayModeID and will be used on next boot
  653. //          <-  depthMode        should be the current depthMode and will be used on the next boot
  654. //          <-  displayCode        the type of display attached.  If the display changes between boots
  655. //                                the displayModeID and the depthMode will be ignored.
  656. //
  657. //=====================================================================================================
  658. GDXErr GraphicsOSSGetCorePref(const RegEntryID *regEntryID, GraphicsPreferred *graphicsPreferred)
  659. {
  660.  
  661.     RegPropertyValueSize valueSize;            // Value size of kPreferredConfigurationName property
  662.     RegPropertyValueSize expectedValueSize = sizeof(GraphicsNonVolatile);
  663.     GraphicsNonVolatile graphicsNonVolatile;                // Actual data stored in NVRAM
  664.     OSErr nameRegistryErr;                                    // In the event of NameRegistry errors
  665.     
  666.     GDXErr err = kGDXErrUnknownError;                        // Assume failure
  667.     
  668.     // Does the propertyName exist? Is the storage provided by the caller big enough to hold data?
  669.  
  670.     nameRegistryErr = RegistryPropertyGetSize(regEntryID, kPreferredConfigurationName, &valueSize);
  671.     if (nameRegistryErr)
  672.     {
  673.         err = kGDXErrOSSNoProperyNameAndValue;
  674.         goto ErrorExit;
  675.     }
  676.  
  677.     if (valueSize > expectedValueSize)
  678.     {
  679.         err = kGDXErrOSSPropertySizeExceedsBuffer;
  680.         goto ErrorExit;
  681.     }
  682.  
  683.     // The propertyValue exists and can be held in the buffer "graphicsNonVolatile"
  684.     nameRegistryErr = RegistryPropertyGet(regEntryID, kPreferredConfigurationName, &graphicsNonVolatile,
  685.             &valueSize);
  686.             
  687.     if (nameRegistryErr)
  688.     {
  689.         err = kGDXErrOSSUnableToGetPropertyValue;
  690.         goto ErrorExit;
  691.     }
  692.     
  693.     if (valueSize != expectedValueSize)
  694.     {
  695.         err = kGDXErrOSSUnexpectedPropertySize;
  696.         goto ErrorExit;
  697.     }
  698.  
  699.     // The kPreferredConfigurationName property was found, so translate the compressed data into
  700.     // the GraphicsPreferred format
  701.     
  702.     err = OSSMapPreference(kOSSMapExpand, &graphicsNonVolatile, graphicsPreferred);
  703.     if (err)
  704.         goto ErrorExit;
  705.     
  706.     err = kGDXErrNoError;
  707.     
  708. ErrorExit:
  709.  
  710.     return err;
  711.  
  712. }
  713.  
  714.  
  715.  
  716. //=====================================================================================================
  717. //
  718. // GraphicsOSSSetHALPref()
  719. //    The OSS calls the Name Registry to get information.  The 'HAL' preferences are saved in the
  720. //    last 4 bytes of the 'gprf' nvram property.  Unlike the SetCorePref, if the NVRAM data isn't the
  721. //    expected size, the code bails without trying to modify the NVRAM structure
  722. //
  723. //            ->    regEntryID            Name Registry RegEntryID that should have the propertyName
  724. //            ->    halData                4 bytes the HAL wishes to save
  725. //                                
  726. //=====================================================================================================
  727. GDXErr GraphicsOSSSetHALPref(const RegEntryID *regEntryID, UInt32 halData)
  728. {
  729.  
  730.     RegPropertyValueSize valueSize;        // Value size of kPreferredConfigurationName property
  731.     RegPropertyValueSize expectedValueSize = sizeof(GraphicsNonVolatile);
  732.     GraphicsNonVolatile graphicsNonVolatile;                // Actual data stored in NVRAM
  733.     OSErr nameRegistryErr;                                    // In the event of NameRegistry errors
  734.     
  735.     GDXErr err = kGDXErrUnknownError;                        // Assume failure
  736.  
  737.         
  738.     // Does the propertyName exist? Is the storage provided by the caller big enough to hold data?
  739.  
  740.     nameRegistryErr = RegistryPropertyGetSize(regEntryID, kPreferredConfigurationName, &valueSize);
  741.     if (nameRegistryErr)
  742.     {    
  743.         err = kGDXErrOSSNoProperyNameAndValue;
  744.         goto ErrorExit;
  745.     }
  746.  
  747.     if (valueSize != expectedValueSize)
  748.     {
  749.         err = kGDXErrOSSUnexpectedPropertySize;
  750.         goto ErrorExit;
  751.     }
  752.  
  753.     // The propertyValue exists and can be held in the buffer 'graphicsNonVolatile'
  754.     nameRegistryErr = RegistryPropertyGet(regEntryID, kPreferredConfigurationName,
  755.             &graphicsNonVolatile, &valueSize);
  756.  
  757.     if (nameRegistryErr)
  758.     {
  759.         err = kGDXErrOSSUnableToGetPropertyValue;
  760.         goto ErrorExit;
  761.     }
  762.     
  763.     if (valueSize != expectedValueSize)
  764.     {
  765.         err = kGDXErrOSSUnexpectedPropertySize;
  766.         goto ErrorExit;
  767.     }
  768.  
  769.     // The kPreferredConfigurationName property was found, so set the HAL data
  770.  
  771.     graphicsNonVolatile.halData = halData;
  772.     
  773.         
  774.     nameRegistryErr = RegistryPropertySet(regEntryID, kPreferredConfigurationName, 
  775.         &graphicsNonVolatile,sizeof(GraphicsNonVolatile));
  776.  
  777.     if (nameRegistryErr)
  778.     {
  779.         err = kGDXErrOSSUnableToSetPropertyValue;
  780.         goto ErrorExit;
  781.     }
  782.  
  783.     err = kGDXErrNoError;
  784.     
  785. ErrorExit:
  786.  
  787.     return err;
  788.  
  789. }
  790.  
  791.  
  792.     
  793. //=====================================================================================================
  794. //
  795. // GraphicsOSSGetHALPref()
  796. //    The OSS calls the Name Registry to get information.  The 'HAL' preferences are saved in the
  797. //    last 4 bytes of the 'gprf' nvram property.  The OSS just passes the data back to the HAL.
  798. //
  799. //            ->    regEntryID            Name Registry RegEntryID that should have the propertyName
  800. //            <-    halData                buffer to hold the hal private data....data can be anything HAL
  801. //                                    wants it to be
  802. //                                
  803. //=====================================================================================================
  804. GDXErr GraphicsOSSGetHALPref(const RegEntryID *regEntryID, UInt32 *halData)
  805. {
  806.  
  807.     RegPropertyValueSize valueSize;                // Value size of kPreferredConfigurationName property
  808.     RegPropertyValueSize expectedValueSize = sizeof(GraphicsNonVolatile);
  809.     GraphicsNonVolatile graphicsNonVolatile;                // Actual data stored in nvram
  810.     OSErr nameRegistryErr;                                    // In the event of NameRegistry errors
  811.     
  812.     GDXErr err = kGDXErrUnknownError;                        // Assume failure
  813.     
  814.     // Does the propertyName exist? Is the storage provided by the caller big enough to hold data?
  815.     
  816.     nameRegistryErr = RegistryPropertyGetSize(regEntryID, kPreferredConfigurationName, &valueSize);
  817.     if (nameRegistryErr)
  818.     {
  819.         err = kGDXErrOSSNoProperyNameAndValue;
  820.         goto ErrorExit;
  821.     }
  822.  
  823.     if (valueSize > expectedValueSize)
  824.     {
  825.         err = kGDXErrOSSPropertySizeExceedsBuffer;
  826.         goto ErrorExit;
  827.     }
  828.  
  829.     // The propertyValue exists and can be held in the buffer 'graphicsNonVolatile'
  830.     nameRegistryErr = RegistryPropertyGet(regEntryID, kPreferredConfigurationName, &graphicsNonVolatile,
  831.                         &valueSize);
  832.  
  833.     if (nameRegistryErr)
  834.     {
  835.         err = kGDXErrOSSUnableToGetPropertyValue;
  836.         goto ErrorExit;
  837.     }
  838.     
  839.     if (valueSize != expectedValueSize)
  840.     {
  841.         err = kGDXErrOSSUnexpectedPropertySize;
  842.         goto ErrorExit;
  843.     }
  844.  
  845.     // The kPreferredConfigurationName property was found.  Copy the HAL data to halPreferred
  846.     *halData = graphicsNonVolatile.halData;
  847.         
  848.     err = kGDXErrNoError;
  849.     
  850. ErrorExit:
  851.  
  852.     return err;
  853.  
  854. }
  855.  
  856.  
  857.  
  858. //=====================================================================================================
  859. //
  860. // OSSMapPreference()
  861. //    Each device is allocated 8 bytes of NVRAM to store non volatile data in the NameRegistry.
  862. //    Since the GDX driver wishes to store more than 8 bytes of data, it is necessary to map the actual
  863. //    data into a format that fits into 8 bytes.  This routine maps in both direction based on the
  864. //    mapDirection.
  865. //
  866. //    The mapping algorithim is as follows:
  867. //    1) mappedDisplayModeID....Direct mapping occurs, since DisplayModeIDs currently have 1 byte 
  868. //        of significance in the LSB, thus mapping can be avoided.
  869. //    2) mappedDepthMode, 0 = kDepthMode1, 1 = kDepthMode2 etc..this is done by substracting kDepthMode1
  870. //        from the depthMode when compressing the data.  kDepthMode1 is added to the mappedDepthMode when
  871. //        the expanding the data
  872. //    3) mappedDisplayCode....Direct mapping occurs.  DisplayCodes should not be greater than 255
  873. //    
  874. //
  875. //            ->    mapDirection            
  876. //            'kOSSMapExpand'     if GraphicsNonVolatile data is being converted into GraphicsPreferred
  877. //            'kOSSMapCompress'    if GraphicsPreferred is being converted into GraphicsNonVolatile
  878. //
  879. //            <>    graphicsNonVolatile
  880. //            if 'kOSSMapExpand', graphicsNonVolatile will be converted/stored in graphicsPreferred
  881. //            if 'kOSSMapCompress', graphicsPreferred will be converted/storedin graphicsNonVolatile
  882. //
  883. //            <>    graphicsPreferred
  884. //            if 'kOSSMapExpand', graphicsNonVolatile will be converted/stored in graphicsPreferred
  885. //            if 'kOSSMapCompress', graphicsPreferred will be converted/stored in graphicsNonVolatile
  886. //                                
  887. //=====================================================================================================
  888. static GDXErr OSSMapPreference(OSSMapDirection mapDirection, GraphicsNonVolatile *graphicsNonVolatile,
  889.         GraphicsPreferred *graphicsPreferred)
  890. {
  891.  
  892.     GDXErr err = kGDXErrNoError;                                // Assume success
  893.  
  894.     
  895.     if (kOSSMapExpand == mapDirection)            
  896.     {
  897.         // Map GraphicsNonVolatile to GraphicsPreferred
  898.         
  899.         graphicsPreferred->displayModeID = graphicsNonVolatile->mappedDisplayModeID;
  900.         graphicsPreferred->depthMode = graphicsNonVolatile->mappedDepthMode + kDepthMode1;
  901.         graphicsPreferred->displayCode = graphicsNonVolatile->mappedDisplayCode;
  902.  
  903.     }
  904.     else
  905.     {                                        
  906.         // Map GraphicsPreferred to GraphicsNonVolatile
  907.         
  908.         graphicsNonVolatile->mappedDisplayModeID = graphicsPreferred->displayModeID;
  909.         graphicsNonVolatile->mappedDepthMode = graphicsPreferred->depthMode - kDepthMode1;
  910.         graphicsNonVolatile->mappedDisplayCode = graphicsPreferred->displayCode;
  911.  
  912.     }
  913.     
  914. ErrorExit:
  915.     
  916.     return err;
  917. }
  918.  
  919.  
  920.  
  921. //=====================================================================================================
  922. //
  923. // GraphicsOSSInstallVBLInterrupts()
  924. //    This routine is specific for VBL interrupts and assumes that a driver's 'driver-ist' only
  925. //    pertains to VBL's.  The Video Services Library (VSL) kHBLService and kFrameService are ignored.
  926. //    Interrogate the HAL to get the interrupt handler, the interrupt enabler, the interrupt disabler,
  927. //    and the VBL 'refCon' (private HAL data that the HAL might need to carry out the functions).
  928. //    This version of GDX interrupt handling isolates the HAL from knowing stuff about how the 
  929. //    handlers are installed.  Conventions interrupt routines must follow:
  930. //        interrupt handler:        clear the hw interrupt source
  931. //        interrupt enabler:        enable the hw interrupt source
  932. //        interrupt disabler:        disable the hw interrupt source and :
  933. //                                return true if interrupts were enabled before the call
  934. //                                return false if interrupts were disabled before the call
  935. //                                
  936. //    
  937. //            ->    regEntryID        Name Registry RegEntryID that should have the propertyName
  938. //                                
  939. //=====================================================================================================
  940. GDXErr GraphicsOSSInstallVBLInterrupts(const RegEntryID *regEntryID)
  941. {
  942.     
  943.     Boolean installVBLInterrupts = false;            // Ask HAL if OSS should install VBL routines
  944.     InterruptEnabler enabler = NULL;                // Use default enabler if HAL's enabler is NULL
  945.     InterruptDisabler disabler = NULL;                // Use default disabler if HAL's disabler is NULL
  946.     
  947.     OSSData *ossData = GraphicsOSSGetOSSData();
  948.     
  949.     GDXErr err = kGDXErrUnknownError;                // Assume failure
  950.     
  951.     
  952.     err = GraphicsHALGetVBLInterruptRoutines(&installVBLInterrupts, &ossData->chainDefault,
  953.             &ossData->halVBLHandler, &ossData->halVBLEnabler, &ossData->halVBLDisabler,
  954.             &ossData->vblRefCon);
  955.     
  956.     if (err)
  957.         goto ErrorExit;
  958.         
  959.     if (installVBLInterrupts)            // The OSS should handle the HAL's vbl interrupts
  960.     {
  961.         // It is possible that OSS should install the routines but doesn't have the InterruptSetMember
  962.         if (ossData->hasInterruptSetMember)
  963.         {
  964.             InterruptServiceIDType vslServiceID;
  965.             OSStatus osStatusErr;
  966.             OSErr osErr;
  967.             
  968.             osStatusErr = GetInterruptFunctions(ossData->interruptSetMember.setID,
  969.                     ossData->interruptSetMember.member,
  970.                     &ossData->defaultRefCon,
  971.                     &ossData->defaultVBLHandler,
  972.                     &ossData->defaultVBLEnabler,
  973.                     &ossData->defaultVBLDisabler );
  974.                     
  975.             if (osStatusErr)
  976.             {
  977.                 err = kGDXErrOSSNoDefaultVBLRoutines;
  978.                 goto ErrorExit;
  979.             }
  980.  
  981.             // If the HAL's enabler/disabler functions are NULL, that indicates that the HAL
  982.             // can use the default enabler/disabler function.  Otherwise, the OSS enabler/disabler
  983.             // functions will be installed.
  984.             // NOTE:  Making a call to InstallInterruptFunctions() with NULL as the enabler/disabler,
  985.             // than the enablers currently installed (the 'default enablers') are used.
  986.             
  987.             if (NULL != ossData->halVBLEnabler)
  988.                 enabler = GraphicsOSSVBLInterruptEnabler;
  989.                 
  990.             if (NULL != ossData->halVBLDisabler)
  991.                 disabler = GraphicsOSSVBLInterruptDisabler;
  992.                 
  993.             osStatusErr = InstallInterruptFunctions(    ossData->interruptSetMember.setID, 
  994.                                                         ossData->interruptSetMember.member, 
  995.                                                         ossData->vblRefCon,
  996.                                                         (InterruptHandler) GraphicsOSSVBLInterruptHandler, 
  997.                                                         enabler, 
  998.                                                         disabler);
  999.             
  1000.             if (osStatusErr)
  1001.             {
  1002.                 err = kGDXErrOSSUnableToInstallVBLRoutines;
  1003.                 goto ErrorExit;
  1004.             }
  1005.  
  1006.             // Successfully installed the routines.
  1007.             ossData->installedHALVBLRoutines = true;
  1008.             
  1009.         }
  1010.         else
  1011.         {
  1012.             err = kGDXErrOSSNoISTProperty;
  1013.             goto ErrorExit;
  1014.         }
  1015.     
  1016.     }
  1017.  
  1018. ErrorExit:
  1019.     
  1020.     return err;
  1021. }
  1022.  
  1023.  
  1024.  
  1025. //=====================================================================================================
  1026. //
  1027. // GraphicsOSSNewInterruptService()
  1028. //    It is necessary to register with the Video Service Library to allow the VSL to run tasks in the
  1029. //    vbl queue when interrupts occur.  The service is installed at each Open and removed on each Close.
  1030. //    Both the interrupt handlers and the VSL must be installed before interrupt handling can occur.
  1031. //    
  1032. //=====================================================================================================
  1033. GDXErr GraphicsOSSNewInterruptService(void)
  1034. {
  1035.     OSSData *ossData = GraphicsOSSGetOSSData();
  1036.     OSErr osErr;
  1037.     
  1038.     GDXErr err = kGDXErrUnknownError;                                // Assume failure
  1039.  
  1040.     if (true == ossData->vslServiceIDValid)                            // VSL services already installed
  1041.     {
  1042.         err = kGDXErrNoError;
  1043.         goto ErrorExit;
  1044.     }
  1045.  
  1046.     // Try to register with the VideoService lib
  1047.     osErr = VSLNewInterruptService(&ossData->regEntryID, kVBLInterruptServiceType, 
  1048.             &ossData->vslServiceID);
  1049.             
  1050.     if (osErr)
  1051.     {
  1052.         err = kGDXErrOSSUnableToInstallVSLService;
  1053.         goto ErrorExit;
  1054.     }
  1055.     
  1056.     // Everything is working and VBLs should be able to run
  1057.     ossData->vslServiceIDValid = true;                        // Have a valid VSLServiceID
  1058.  
  1059.     err = kGDXErrNoError;
  1060.  
  1061. ErrorExit:
  1062.  
  1063.     return err;
  1064.  
  1065. }
  1066.  
  1067.  
  1068.  
  1069. //=====================================================================================================
  1070. //
  1071. // GraphicsOSSDisposeInterruptService()
  1072. //    Each time the driver is closed, it is necessary to 'unregister' with the VSL so that tasks
  1073. //    in the VBL queue for the driver can be moved to the the 'system' VBL task queue.
  1074. //    NOTE!!! The interrupt handler DOES NOT CHECK to ensure that there is a service registered with the
  1075. //    VSL before calling VSLDoInterruptService.  That means that interrupts must be turned off before
  1076. //    this routine is called.  As a sanity check, the OSS will make sure interrupts are off.
  1077. //    
  1078. //=====================================================================================================
  1079. GDXErr GraphicsOSSDisposeInterruptService(void)
  1080. {
  1081.  
  1082.     VDFlagRecord flag;                                    // Check status of interrupts before disposing
  1083.     OSSData *ossData = GraphicsOSSGetOSSData();
  1084.     OSErr osErr;
  1085.     
  1086.     GDXErr err = kGDXErrUnknownError;                    // Assume failure
  1087.  
  1088.     if (false == ossData->vslServiceIDValid)                        // VSL services already disposed
  1089.     {
  1090.         err = kGDXErrNoError;
  1091.         goto ErrorExit;
  1092.     }
  1093.  
  1094.     // Make sure interrupts are disabled.  It would be bad to remove the VSL service and then get
  1095.     // an interrupt.
  1096.     
  1097.     err = GraphicsCoreGetInterrupt(&flag);
  1098.  
  1099.     if (0 == flag.csMode)             
  1100.     {
  1101.         // Can't remove VSL service because interrupts are still occuring
  1102.         err = kGDXErrOSSInterruptSourceStillActive;
  1103.         goto ErrorExit;
  1104.     }
  1105.     
  1106.     // Mark ID as invalid prior to disposal, in order to avoid the unlikely race condition that
  1107.     // a HAL which only uses software timer interrupts and didn't properly kill it is set off.
  1108.     
  1109.     ossData->vslServiceIDValid = false;                        
  1110.  
  1111.     osErr = VSLDisposeInterruptService(ossData->vslServiceID);
  1112.  
  1113.     if (osErr)
  1114.     {
  1115.         err = kGDXErrOSSUnableToDisposeVSLService;
  1116.         ossData->vslServiceIDValid = true;            // Mark ID as valid, since disposal unsuccessful
  1117.         goto ErrorExit;
  1118.     }
  1119.  
  1120.     err = kGDXErrNoError;
  1121.  
  1122. ErrorExit:
  1123.  
  1124.     return err;
  1125.  
  1126. }
  1127.  
  1128.  
  1129.  
  1130. //=====================================================================================================
  1131. //
  1132. // GraphicsOSSSetVBLInterrupt()
  1133. //    This routine is used to enable/disable VBL interrupts.  The OSS obtained all the information
  1134. //     regarding how interrupts should be handled via the GraphicsHALGetVBLInterruptRoutines() call.
  1135. //    Therefore, it knows whether to call default enablers/disablers, or the ones provided by the HAL.
  1136. //
  1137. //        -> enableInterrupts        'true' if interrupts should be enabled, 'false' otherwise.
  1138. //
  1139. //        <- Boolean                If disabling interrupts, then this is 'true' if interrupts were
  1140. //                                previously enabled, false otherwise.
  1141. //                                It is UNDEFINED when enabling interrupts.
  1142. //
  1143. //=====================================================================================================
  1144. Boolean GraphicsOSSSetVBLInterrupt(Boolean enableInterrupts)
  1145. {
  1146.     OSSData *ossData = GraphicsOSSGetOSSData();
  1147.     InterruptSourceState interruptSourceState;
  1148.     Boolean originallyEnabled;
  1149.     
  1150.     if (enableInterrupts)
  1151.     {
  1152.         if (NULL == ossData->halVBLEnabler)
  1153.             GraphicsOSSVBLDefaultEnabler();
  1154.         else
  1155.             GraphicsOSSVBLInterruptEnabler(ossData->interruptSetMember, ossData->vblRefCon);
  1156.             
  1157.     }
  1158.     else
  1159.     {
  1160.         if (NULL == ossData->halVBLDisabler)
  1161.             originallyEnabled = GraphicsOSSVBLDefaultDisabler();
  1162.         else
  1163.             originallyEnabled = GraphicsOSSVBLInterruptDisabler(ossData->interruptSetMember,
  1164.                     ossData->vblRefCon);
  1165.     }
  1166.     
  1167.  
  1168.     return originallyEnabled;
  1169. }
  1170.  
  1171.  
  1172. //=====================================================================================================
  1173. //
  1174. // GraphicsOSSVBLInterruptHandler()
  1175. //
  1176. //    This routine is specific for VBL interrupts and assumes that a driver's "driver-ist" only
  1177. //    pertains to vbl's.
  1178. //    This routine is the entry point to for the HAL's vbl interrupt handler.  It assumes that
  1179. //    once the vbl interrupt source has been cleared by the HAL, it is okay to call the videoservice lib
  1180. //    to run tasks in the vbl queue.  It assume that it can return kIsrIsComplete to indicate there are
  1181. //    no more interrupt set members that care about the interrupt and that the interrupt processing is
  1182. //    finished.
  1183. //
  1184. //            ->    interruptSetMember    interrupt occurred for this InterruptSetMember
  1185. //
  1186. //    For this routine, the relevant fields of the 'InterruptSetMember' structure are as follows:
  1187. //
  1188. //            -> setID
  1189. //            Interrupt occured in this set.  OSS assumes there is only one relevant set per driver, i.e,
  1190. //            OSS is only handling VBL interrupts
  1191. //
  1192. //            -> member
  1193. //            Member for which the interrupt occured.  The OS never looks at the member and since the OSS
  1194. //            assumes there is only 1 relvant member per driver, it is being ignored.
  1195. //
  1196. //            -> vblRefCon
  1197. //            The refCon that a HAL might need to handle interrupts.  The OS never looks at the refCon
  1198. //            and the OSS just passes it to the HAL
  1199. //
  1200. //            -> theIntCount            don't care
  1201. //
  1202. //=====================================================================================================
  1203. static InterruptMemberNumber GraphicsOSSVBLInterruptHandler(InterruptSetMember interruptSetMember,
  1204.             void *vblRefCon, UInt32 theIntCount)
  1205. {
  1206.     
  1207.     OSSData *ossData = GraphicsOSSGetOSSData();
  1208.  
  1209.     (*ossData->halVBLHandler)(vblRefCon);                // Call the HALs Handler
  1210.  
  1211.     (void) VSLDoInterruptService(ossData->vslServiceID);
  1212.  
  1213.     return kIsrIsComplete;
  1214. }
  1215.  
  1216.  
  1217.  
  1218. //=====================================================================================================
  1219. //
  1220. // GraphicsOSSVBLInterruptEnabler()
  1221. //
  1222. //    This routine is specific for VBL interrupts and assumes that a driver's 'driver-ist' only
  1223. //    pertains to VBL's.
  1224. //    This routine is the entry point to for the HAL's VBL interrupt enabler.  It just calls the
  1225. //    HAL's VBL interrupt enabler.  If the HAL's vbl interrupt enabler was NULL, this routine
  1226. //    is not installed since the default enabler and disabler routines are used.
  1227. //
  1228. //            ->    interruptSetMember    interrupt occurred for this InterruptSetMember
  1229. //
  1230. //    For this routine, the relevant fields of the 'InterruptSetMember' structure are as follows:
  1231. //
  1232. //            -> setID
  1233. //            Disable the interrupt source for set.  OSS assumes there is only one relevant set per 
  1234. //            driver, i.e., the OSS is only handling VBL interrupts.
  1235. //
  1236. //            -> member
  1237. //            Member for which the interrupt occured.  The OS never looks at the member and since the OSS
  1238. //            assumes there is only 1 relvant member per driver, it is being ignored.
  1239. //
  1240. //            -> vblRefCon
  1241. //            The refCon that a HAL might need to handle interrupts.  The OS never looks at the refCon
  1242. //            and the OSS just passes it to the HAL.
  1243. //
  1244. //=====================================================================================================
  1245. static void GraphicsOSSVBLInterruptEnabler(InterruptSetMember interruptSetMember, void *vblRefCon)
  1246. {
  1247.     OSSData *ossData = GraphicsOSSGetOSSData();
  1248.     (*ossData->halVBLEnabler)(vblRefCon);                    // HAL VBL enabler
  1249.  
  1250.     // Call default enabler if HAL instructed the OSS to 'chain' the defaults
  1251.     if (ossData->chainDefault)                                
  1252.         GraphicsOSSVBLDefaultEnabler();    
  1253. }
  1254.  
  1255.  
  1256.  
  1257. //=====================================================================================================
  1258. //
  1259. // GraphicsOSSVBLInterruptDisabler()
  1260. //
  1261. //    This routine is specific for VBL interrupts and assumes that a driver's "driver-ist" only
  1262. //    pertains to vbl's.  If the HAL's vbl interrupt enabler was NULL, this routine is not installed
  1263. //    since the default enabler and disabler routines are used.
  1264. //
  1265. //    This routine is the entry point to for the HAL's vbl interrupt disabler.  It just calls the
  1266. //    HAL's vbl interrupt enabler.  The HAL should:
  1267. //                                return true if interrupts were enabled before the call
  1268. //                                return false if interrupts were disabled before the call
  1269. //
  1270. //            ->    interruptSetMember    interrupt occurred for this InterruptSetMember
  1271. //
  1272. //    For this routine, the relevant fields of the 'InterruptSetMember' structure are as follows:
  1273. //
  1274. //            -> setID
  1275. //            Disable the interrupt source for set.  OSS assumes there is only one relevant set per 
  1276. //            driver, i.e., the OSS is only handling VBL interrupts.
  1277. //
  1278. //            -> member
  1279. //            Member for which the interrupt occured.  The OS never looks at the member and since the OSS
  1280. //            assumes there is only 1 relvant member per driver, it is being ignored.
  1281. //
  1282. //            -> vblRefCon
  1283. //            The refCon that a HAL might need to handle interrupts.  The OS never looks at the refCon
  1284. //            and the OSS just passes it to the HAL.
  1285. //
  1286. //=====================================================================================================
  1287. static Boolean GraphicsOSSVBLInterruptDisabler(InterruptSetMember interruptSetMember, 
  1288.             void *vblRefCon)
  1289. {
  1290.     OSSData *ossData = GraphicsOSSGetOSSData();
  1291.     InterruptSourceState interruptSourceState;
  1292.     Boolean originallyEnabled;
  1293.  
  1294.     interruptSourceState =  (*ossData->halVBLDisabler)(vblRefCon);
  1295.  
  1296.     if (ossData->chainDefault)                                    // Call default disabler if HAl didn't
  1297.         interruptSourceState = GraphicsOSSVBLDefaultDisabler();    // disable the external interrupt source
  1298.     
  1299.     if (kSourceWasEnabled == interruptSourceState)
  1300.         originallyEnabled = true;
  1301.     else
  1302.         originallyEnabled = false;
  1303.  
  1304.     return originallyEnabled;
  1305. }
  1306.  
  1307.  
  1308.  
  1309. //=====================================================================================================
  1310. //
  1311. // GraphicsOSSVBLDefaultEnabler()
  1312. //    This routine is specific for VBL interrupts and assumes that a driver's 'driver-ist' only
  1313. //    pertains to VBLs.  If the HAL doesn't know about the external interrupt source, it can
  1314. //    call this routine after hitting its own hardware to reenable interrupts.
  1315. //
  1316. //=====================================================================================================
  1317. void GraphicsOSSVBLDefaultEnabler(void)
  1318. {
  1319.     OSSData *ossData = GraphicsOSSGetOSSData();
  1320.     (*ossData->defaultVBLEnabler)(ossData->interruptSetMember, NULL);
  1321. }
  1322.  
  1323.  
  1324.  
  1325. //=====================================================================================================
  1326. //
  1327. // GraphicsOSSVBLDefaultDisabler()
  1328. //
  1329. //    This routine is specific for VBL interrupts and assumes that a driver's 'driver-ist' only
  1330. //    pertains to VBLs.  If the HAL doesn't know about the external interrupt source, it can
  1331. //    call this routine before hitting hardware to disable interrupts.
  1332. //
  1333. //    returns        'true' if the external interrupts was originally enabled, 'false' otherwise.
  1334. //
  1335. //=====================================================================================================
  1336. Boolean GraphicsOSSVBLDefaultDisabler(void)
  1337. {
  1338.     OSSData *ossData = GraphicsOSSGetOSSData();
  1339.     InterruptSourceState interruptSourceState;
  1340.     Boolean originallyEnabled;
  1341.  
  1342.  
  1343.     interruptSourceState =  (*ossData->defaultVBLDisabler)(ossData->interruptSetMember,nil);
  1344.  
  1345.     if (kSourceWasEnabled == interruptSourceState)
  1346.         originallyEnabled = true;
  1347.     else
  1348.         originallyEnabled = false;
  1349.  
  1350.     return originallyEnabled;
  1351. }
  1352.  
  1353. //=====================================================================================================
  1354. //
  1355. // GraphicsOSSDoVSLInterruptService()
  1356. //
  1357. //    This routine simply calls the VSL to service the VBL tasks associated with this graphics device.
  1358. //
  1359. //    Normally, a HAL implementaion would NEVER have to call this routine.  However, in the rare event
  1360. //    that the HAL's hardware does not support true hardware interrupts, then the HAL should call this
  1361. //    during its 'simulated VBL' routine to give allow the OS to serice items in its VBL task queue.
  1362. //
  1363. //=====================================================================================================
  1364. void GraphicsOSSDoVSLInterruptService(void)
  1365. {
  1366.     
  1367.     OSSData *ossData = GraphicsOSSGetOSSData();
  1368.  
  1369.     if (ossData->vslServiceIDValid)
  1370.         (void) VSLDoInterruptService(ossData->vslServiceID);
  1371. }
  1372.  
  1373.  
  1374.